"use strict";

$(document).ready(function() {

    var size;
    var plateau;
    var commands;
    var pauseSecs;

    function parse() {
        commands = $('#commands').val().split('\n').filter(function(item){return item.trim()});
        if (invalidInput(commands)) return;        
        size = commands.shift();
        commands.splice(-1, 1); // remove size and quit
        pauseSecs = parseInt($("#pauseSecs").val());
        initializePlateauAndRun();
    }

    function initializePlateauAndRun() {
        plateau = new Array();
        for (var i = 0; i < size; i++) {
            plateau[i] = new Array();
            plateau[i].push(i);
            plateau[i].pos = i;
        }
        draw();
        setTimeout(nextCommand, pauseSecs);
    }

    function nextCommand() {
        runCommand.apply(this, commands.shift().split(" "));
        draw();
        if (commands.length > 0) {
            setTimeout(nextCommand, pauseSecs);
        }
    }

    function runCommand(action, source, prep, target) {
        source = parseInt(source);
        target = parseInt(target);
        if (source === target || plateau[source].pos === plateau[target].pos) {
            console.log("skipping command: {0} {1} {2} {3}".format(action, source, prep, target));
            return;
        }
        if (action === 'move') {
            clean(source);
        }
        if (prep === 'onto' ) {
            clean(target);
        }
        var source_array = plateau[plateau[source].pos];
        var idx_source = source_array.indexOf(source);
        var move = source_array.splice(idx_source, source_array.length - idx_source);
        for (var e of move) {
            plateau[e].pos = plateau[target].pos;
        }
        Array.prototype.push.apply(plateau[plateau[target].pos], move);
    }

    function clean(block) {
        var idx_block = plateau[block].pos;
        while (plateau[idx_block].slice(-1)[0] !== block) {
            var popped = plateau[idx_block].pop();
            plateau[popped].pos = popped;
            plateau[popped].push(popped);
        }
    }

    function draw() {
        var canvas = document.getElementById("canvy"); 
        var ctx = canvas.getContext("2d");
        var cell_width = canvas.width/size;
        var cell_height = canvas.height/size;

        // background
        ctx.fillStyle = "#CCCCFF";
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        // blocks
        ctx.font = "20px Tahoma";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        for (var i = 0; i < size; i++) {
            for (var j = 0; j < plateau[i].length; j++) {
                var x = cell_width * i;
                var y = cell_height * (size - (j + 1));
                ctx.fillStyle = "#7777FF";
                ctx.fillRect(x, y, cell_width, cell_height);
                ctx.fillStyle = "#CCCCFF";
                ctx.fillText(plateau[i][j], x + (cell_width / 2), y + (cell_height / 2));
            }
        }

        // column outline
        ctx.strokeStyle = "#AAAAFF";
        ctx.beginPath();
        for (var i = 1; i < size; i++)
        {
            ctx.moveTo(cell_width * i, 0);
            ctx.lineTo(cell_width * i, canvas.height);
        }
        ctx.stroke();

    }

    function invalidInput(lines) {
        var errors = false;
        if (lines.length < 3 ) {
            message('not enough commands');
            errors = true;
            if (lines.length == 0) return errors;
        }
        if (!lines[0].match(/^[2-9]$/)) {
            message('invalid board size: 2..9');
            errors = true;
        }
        for (var i = 1; i < lines.length - 1; i++) {
            if(!lines[i].match(/^(?:move|pile)\s[0-9]\s(?:onto|over)\s[0-9]$/)) {
                message('invalid command: ' + lines[i]);
                errors = true;
            }
        }
        if (lines[lines.length - 1] !== 'quit') {
            message('last command must be quit');
            errors = true;
        }
        return errors;
    }

    function message(msg) {
        var li = document.createElement("li");
        li.appendChild(document.createTextNode(msg));
        document.getElementById('messages').appendChild(li);
    }

    $("#form").submit(function(){ parse(); return false;});

    // printf
    if (!String.prototype.format) {
      String.prototype.format = function() {
        var args = arguments;
        return this.replace(/{(\d+)}/g, function(match, number) { 
          return typeof args[number] != 'undefined'
            ? args[number]
            : match
          ;
        });
      };
    }

});
